package gandalf.controller;

import gandalf.PersistenceManager;
import gandalf.controller.exceptions.NonexistentEntityException;
import gandalf.model.Stranka;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import gandalf.model.Nakup;
import java.util.ArrayList;
import java.util.List;
import gandalf.model.Rezervacija;

public class StrankaJpaController {

    public EntityManager getEntityManager() {
        return PersistenceManager.createEntityManager();
    }

    public Long create(Stranka stranka) {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            em.persist(stranka);
            em.getTransaction().commit();

            return stranka.getId();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Stranka stranka) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            System.out.println("\n\n ID STRANKE KI SE UREJA: " + stranka.getId());
            Stranka persistentStranka = em.find(Stranka.class, stranka.getId());
            List<Nakup> nakupiOld = persistentStranka.getNakupi();
            List<Nakup> nakupiNew = stranka.getNakupi();
            List<Rezervacija> rezervacijeOld = persistentStranka.getRezervacije();
            List<Rezervacija> rezervacijeNew = stranka.getRezervacije();
            List<Nakup> attachedNakupiNew = new ArrayList<Nakup>();
            for (Nakup nakupiNewNakupToAttach : nakupiNew) {
                nakupiNewNakupToAttach = em.getReference(nakupiNewNakupToAttach.getClass(), nakupiNewNakupToAttach.getId());
                attachedNakupiNew.add(nakupiNewNakupToAttach);
            }
            nakupiNew = attachedNakupiNew;
            stranka.setNakupi(nakupiNew);
            List<Rezervacija> attachedRezervacijeNew = new ArrayList<Rezervacija>();
            for (Rezervacija rezervacijeNewRezervacijaToAttach : rezervacijeNew) {
                rezervacijeNewRezervacijaToAttach = em.getReference(rezervacijeNewRezervacijaToAttach.getClass(), rezervacijeNewRezervacijaToAttach.getId());
                attachedRezervacijeNew.add(rezervacijeNewRezervacijaToAttach);
            }
            rezervacijeNew = attachedRezervacijeNew;
            stranka.setRezervacije(rezervacijeNew);
            stranka = em.merge(stranka);
            for (Nakup nakupiOldNakup : nakupiOld) {
                if (!nakupiNew.contains(nakupiOldNakup)) {
                    nakupiOldNakup.setStranka(null);
                    nakupiOldNakup = em.merge(nakupiOldNakup);
                }
            }
            for (Nakup nakupiNewNakup : nakupiNew) {
                if (!nakupiOld.contains(nakupiNewNakup)) {
                    Stranka oldStrankaOfNakupiNewNakup = nakupiNewNakup.getStranka();
                    nakupiNewNakup.setStranka(stranka);
                    nakupiNewNakup = em.merge(nakupiNewNakup);
                    if (oldStrankaOfNakupiNewNakup != null && !oldStrankaOfNakupiNewNakup.equals(stranka)) {
                        oldStrankaOfNakupiNewNakup.getNakupi().remove(nakupiNewNakup);
                        oldStrankaOfNakupiNewNakup = em.merge(oldStrankaOfNakupiNewNakup);
                    }
                }
            }
            for (Rezervacija rezervacijeOldRezervacija : rezervacijeOld) {
                if (!rezervacijeNew.contains(rezervacijeOldRezervacija)) {
                    rezervacijeOldRezervacija.setStranka(null);
                    rezervacijeOldRezervacija = em.merge(rezervacijeOldRezervacija);
                }
            }
            for (Rezervacija rezervacijeNewRezervacija : rezervacijeNew) {
                if (!rezervacijeOld.contains(rezervacijeNewRezervacija)) {
                    Stranka oldStrankaOfRezervacijeNewRezervacija = rezervacijeNewRezervacija.getStranka();
                    rezervacijeNewRezervacija.setStranka(stranka);
                    rezervacijeNewRezervacija = em.merge(rezervacijeNewRezervacija);
                    if (oldStrankaOfRezervacijeNewRezervacija != null && !oldStrankaOfRezervacijeNewRezervacija.equals(stranka)) {
                        oldStrankaOfRezervacijeNewRezervacija.getRezervacije().remove(rezervacijeNewRezervacija);
                        oldStrankaOfRezervacijeNewRezervacija = em.merge(oldStrankaOfRezervacijeNewRezervacija);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = stranka.getId();
                if (findStranka(id) == null) {
                    throw new NonexistentEntityException("The stranka with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }


    public void uredi(Stranka stranka) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            System.out.println("\n\n ID STRANKE KI SE UREJA: " + stranka.getId());
            
            stranka = em.merge(stranka);
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = stranka.getId();
                if (findStranka(id) == null) {
                    throw new NonexistentEntityException("The stranka with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }



    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Stranka stranka;
            try {
                stranka = em.getReference(Stranka.class, id);
                stranka.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The stranka with id " + id + " no longer exists.", enfe);
            }
            List<Nakup> nakupi = stranka.getNakupi();
            for (Nakup nakupiNakup : nakupi) {
                nakupiNakup.setStranka(null);
                nakupiNakup = em.merge(nakupiNakup);
            }
            List<Rezervacija> rezervacije = stranka.getRezervacije();
            for (Rezervacija rezervacijeRezervacija : rezervacije) {
                rezervacijeRezervacija.setStranka(null);
                rezervacijeRezervacija = em.merge(rezervacijeRezervacija);
            }
            em.remove(stranka);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Stranka> findStrankaEntities() {
        return findStrankaEntities(true, -1, -1);
    }

    public List<Stranka> findStrankaEntities(int maxResults, int firstResult) {
        return findStrankaEntities(false, maxResults, firstResult);
    }

    private List<Stranka> findStrankaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Stranka as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public List<Stranka> vrniVseClane(boolean all) {
        List<Stranka> clani = new ArrayList<Stranka>();
        EntityManager em = null;
        try {
            em = getEntityManager();
            Query q = null;
            if (all) {
                q = em.createQuery("select object(o) from Stranka as o ORDER BY o.priimek ASC");
            }
            clani = q.getResultList();
           
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            if (em != null) {
                em.close();
            }
        }
        return clani;
    }

    public Stranka findStranka(Long id) {
        EntityManager em = getEntityManager();
        try {

            return em.find(Stranka.class, id);
        } finally {
            em.close();
        }
    }

    public Stranka findStrankaWithNakupi(Long id) {
        EntityManager em = getEntityManager();
        try {

            Stranka s = em.find(Stranka.class, id);
            List<Nakup> nakupi = new ArrayList<Nakup>();
            Query getNakupi = em.createQuery("select n from Nakup as n where n.stranka = :stranka");
            getNakupi.setParameter("stranka", s);
            nakupi = getNakupi.getResultList();
            s.setNakupi(nakupi);
            return s;
        } finally {
            em.close();
        }
    }

    public int getStrankaCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Stranka as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

    public Long avtenticiraj(String email, String password) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("SELECT s FROM Stranka as s WHERE s.email = :email").setParameter("email", email);

            Object stranka = q.getSingleResult();
            if (stranka != null && stranka instanceof Stranka) {
                Stranka s = (Stranka) stranka;

                // preverimo password
                if (password.equals(s.getPassword())) {

                    return s.getId();


                }

            }
        } catch (Exception exc) {
            exc.printStackTrace();
        } finally {
            em.close();
        }

        return null;
    }

    public boolean obstaja(String email) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("SELECT s FROM Stranka as s WHERE s.email = :email").setParameter("email", email);

            Object stranka = q.getSingleResult();
            if (stranka != null && stranka instanceof Stranka) {
                Stranka s = (Stranka) stranka;

                return true;

            }
        } catch (Exception exc) {
            exc.printStackTrace();
        } finally {
            em.close();
        }

        return false;
    }
}
